package lol.clann.minecraft.springboot.bukkit.plugin.logger;

import org.bukkit.ChatColor;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.event.Level;


/**
 *
 * @author pyz
 * @date 2019/5/5 10:30 PM
 */
public abstract class AbstractLogger implements Logger {

    private String name;
    private int trace = 50;
    private int debug = 40;
    private int info = 30;
    private int warn = 20;
    private int error = 10;
    private int level = info;
    private final int stackDeep;

    protected AbstractLogger(String name, int stackDeep) {
        this.name = name;
        this.stackDeep = stackDeep;
        String level = System.getProperty("slf4j.logger.level." + name);
        if (level == null) {
            return;
        }
        this.info("slf4j.logger.level." + name + "=" + level);
        if (level.equalsIgnoreCase("trace")) {
            this.level = trace;
        } else if (level.equalsIgnoreCase("debug")) {
            this.level = debug;
        } else if (level.equalsIgnoreCase("info")) {
            this.level = info;
        } else if (level.equalsIgnoreCase("warn")) {
            this.level = warn;
        } else if (level.equalsIgnoreCase("error")) {
            this.level = error;
        }
    }

    public void setTrace(boolean trace) {
        int threshold = this.trace;
        level = trace ? threshold : (level >= threshold ? threshold - 1 : level);
    }

    public void setDebug(boolean debug) {
        int threshold = this.debug;
        level = debug ? threshold : (level >= threshold ? threshold - 1 : level);
    }

    public void setInfo(boolean info) {
        int threshold = this.info;
        level = info ? threshold : (level >= threshold ? threshold - 1 : level);
    }

    public void setWarn(boolean warn) {
        int threshold = this.warn;
        level = warn ? threshold : (level >= threshold ? threshold - 1 : level);
    }

    public void setError(boolean error) {
        int threshold = this.error;
        level = error ? threshold : (level >= threshold ? threshold - 1 : level);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public boolean isTraceEnabled() {
        return needLevel(this.trace);
    }

    @Override
    public void trace(String s) {
        log(trace, Level.TRACE, ChatColor.GRAY, s, null, null);
    }

    @Override
    public void trace(String s, Object o) {
        log(trace, Level.TRACE, ChatColor.GRAY, s, null, o);
    }

    @Override
    public void trace(String s, Object o, Object o1) {
        log(trace, Level.TRACE, ChatColor.GRAY, s, null, o, o1);
    }

    @Override
    public void trace(String s, Object... objects) {
        log(trace, Level.TRACE, ChatColor.GRAY, s, null, objects);
    }

    @Override
    public void trace(String s, Throwable throwable) {
        log(trace, Level.TRACE, ChatColor.GRAY, s, throwable, null);
    }

    @Override
    public boolean isTraceEnabled(Marker marker) {
        return false;
    }

    @Override
    public void trace(Marker marker, String s) {

    }

    @Override
    public void trace(Marker marker, String s, Object o) {

    }

    @Override
    public void trace(Marker marker, String s, Object o, Object o1) {

    }

    @Override
    public void trace(Marker marker, String s, Object... objects) {

    }

    @Override
    public void trace(Marker marker, String s, Throwable throwable) {

    }

    @Override
    public boolean isDebugEnabled() {
        return this.needLevel(this.debug);
    }

    @Override
    public void debug(String s) {
        log(debug, Level.DEBUG, ChatColor.BLUE, s, null, null);
    }

    @Override
    public void debug(String s, Object o) {
        log(debug, Level.DEBUG, ChatColor.BLUE, s, null, o);
    }

    @Override
    public void debug(String s, Object o, Object o1) {
        log(debug, Level.DEBUG, ChatColor.BLUE, s, null, o, o1);
    }

    @Override
    public void debug(String s, Object... objects) {
        log(debug, Level.DEBUG, ChatColor.BLUE, s, null, objects);
    }

    @Override
    public void debug(String s, Throwable throwable) {
        log(debug, Level.DEBUG, ChatColor.BLUE, s, throwable, null);
    }

    @Override
    public boolean isDebugEnabled(Marker marker) {
        return true;
    }

    @Override
    public void debug(Marker marker, String s) {

    }

    @Override
    public void debug(Marker marker, String s, Object o) {

    }

    @Override
    public void debug(Marker marker, String s, Object o, Object o1) {

    }

    @Override
    public void debug(Marker marker, String s, Object... objects) {

    }

    @Override
    public void debug(Marker marker, String s, Throwable throwable) {

    }

    @Override
    public boolean isInfoEnabled() {
        return this.needLevel(this.info);
    }

    @Override
    public void info(String s) {
        log(info, Level.INFO, ChatColor.GREEN, s, null, null);
    }

    @Override
    public void info(String s, Object o) {
        log(info, Level.INFO, ChatColor.GREEN, s, null, o);
    }

    @Override
    public void info(String s, Object o, Object o1) {
        log(info, Level.INFO, ChatColor.GREEN, s, null, o, o1);
    }

    @Override
    public void info(String s, Object... objects) {
        log(info, Level.INFO, ChatColor.GREEN, s, null, objects);
    }

    @Override
    public void info(String s, Throwable throwable) {
        log(info, Level.INFO, ChatColor.GREEN, s, throwable, null);
    }

    @Override
    public boolean isInfoEnabled(Marker marker) {
        return true;
    }

    @Override
    public void info(Marker marker, String s) {

    }

    @Override
    public void info(Marker marker, String s, Object o) {

    }

    @Override
    public void info(Marker marker, String s, Object o, Object o1) {

    }

    @Override
    public void info(Marker marker, String s, Object... objects) {

    }

    @Override
    public void info(Marker marker, String s, Throwable throwable) {

    }

    @Override
    public boolean isWarnEnabled() {
        return this.needLevel(this.warn);
    }

    @Override
    public void warn(String s) {
        log(warn, Level.WARN, ChatColor.GOLD, s, null, null);
    }

    @Override
    public void warn(String s, Object o) {
        log(warn, Level.WARN, ChatColor.GOLD, s, null, o);
    }

    @Override
    public void warn(String s, Object o, Object o1) {
        log(warn, Level.WARN, ChatColor.GOLD, s, null, o, o1);
    }

    @Override
    public void warn(String s, Object... objects) {
        log(warn, Level.WARN, ChatColor.GOLD, s, null, objects);
    }

    @Override
    public void warn(String s, Throwable throwable) {
        log(warn, Level.WARN, ChatColor.GOLD, s, throwable, null);
    }

    @Override
    public boolean isWarnEnabled(Marker marker) {
        return true;
    }

    @Override
    public void warn(Marker marker, String s) {

    }

    @Override
    public void warn(Marker marker, String s, Object o) {

    }

    @Override
    public void warn(Marker marker, String s, Object o, Object o1) {

    }

    @Override
    public void warn(Marker marker, String s, Object... objects) {

    }

    @Override
    public void warn(Marker marker, String s, Throwable throwable) {

    }

    @Override
    public boolean isErrorEnabled() {
        return this.needLevel(error);
    }

    @Override
    public void error(String s) {
        log(error, Level.ERROR, ChatColor.RED, s, null, null);
    }

    @Override
    public void error(String s, Object o) {
        log(error, Level.ERROR, ChatColor.RED, s, null, o);
    }

    @Override
    public void error(String s, Object o, Object o1) {
        log(error, Level.ERROR, ChatColor.RED, s, null, o, o1);
    }

    @Override
    public void error(String s, Object... objects) {
        log(error, Level.ERROR, ChatColor.RED, s, null, objects);
    }

    @Override
    public void error(String s, Throwable throwable) {
        log(error, Level.ERROR, ChatColor.RED, s, throwable, null);
    }

    @Override
    public boolean isErrorEnabled(Marker marker) {
        return true;
    }

    @Override
    public void error(Marker marker, String s) {

    }

    @Override
    public void error(Marker marker, String s, Object o) {

    }

    @Override
    public void error(Marker marker, String s, Object o, Object o1) {

    }

    @Override
    public void error(Marker marker, String s, Object... objects) {

    }

    @Override
    public void error(Marker marker, String s, Throwable throwable) {

    }

    protected void log(int nlevel, Level level, ChatColor color, String message, Throwable e, Object... params) {
        if (this.level < nlevel) {
            return;
        }
        directLog(level, format(color, message, params), e);
    }

    protected String format(ChatColor color, String message, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(color);
        sb.append(getPrefix());
        sb.append(ChatColor.WHITE);
        if (message == null || params == null || params.length == 0) {
            return message == null ? sb.toString() : sb.append(message).toString();
        }
        String[] ss = message.split("\\{\\}");
        for (int i = 0; i < ss.length; i++) {
            sb.append(ss[i]);
            if (i < params.length) {
                sb.append(params[i] == null ? "" : String.valueOf(params[i]));
            } else {
                sb.append("{}");
            }
        }
        return sb.toString();
    }

    /**
     *
     * @param level
     * @param message
     * @param e
     */
    protected abstract void directLog(Level level, String message, Throwable e);

    private String getPrefix() {
        StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[stackDeep];
        return stackTrace.getFileName().substring(0, stackTrace.getFileName().length() - 5) + ":" + stackTrace.getLineNumber() + " ";
    }

    private boolean needLevel(int level) {
        return this.level >= level;
    }

}



